#ifndef __M_SERVER_H__
#define __M_SERVER_H__
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
#include <cstring>
#include <ctime>
#include <functional>
#include <unordered_map>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <typeinfo>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>

//实现日志打印[时间 行数]日志内容
#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL INF //通过宏控制我们打印的日志等级

#define LOG(level, format, ...) do{\
        if(level<LOG_LEVEL) break;\
        time_t t=time(NULL);\
        struct tm *ltm=localtime(&t);\
        char tmp[32]={0};\
        strftime(tmp,31,"%H:%M:%S",ltm);\
        fprintf(stdout,"[%p %s %s:%d] " format "\n", (void*)pthread_self(), tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
    }while(0)

#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)

//buffer实现我们的缓冲区类
//思想：关键在于数据的写入和读取，我们使用两个指针指向写入和读取的vector<char>位置
//写入：写入指针在哪，就从哪里开始写入，如果后面的空间不够：考虑移动到前面或者扩容，写入成功指针向后偏移
//读取：读取指针在哪，就从哪里开始读取，前提是有数据可读，可读数据大小：写入指针位置减去读取位置指针
#define BUFFFER_DEFAULT_SIZE 1024
class Buffer
{
    private:
        std::vector<char> _buffer; //buffer缓冲区
        //这些都是相对偏移量，不是绝对位置
        uint64_t _writer_idx; //写入指针位置
        uint64_t _reader_idx; //读取指针位置

    public:
        //获取当前写入位置地址 
        //获取当前读取位置地址
        //获取前沿空间大小，就是写入位置的后面
        //获取后沿空间大小，就是读取位置的前面
        //将写入位置向右移动指定长度
        //将读取位置向右移动指定长度
        //确保可写空间足够(移动+扩容)
        //确保有可读空间，且获取可读空间大小
        //写入数据
        //读取数据
        //清理缓冲区

        //Buffer构造函数
        Buffer():_reader_idx(0),_writer_idx(0),_buffer(BUFFFER_DEFAULT_SIZE){}

        //获取_buffer开始的地址
        char *Begin() {return &*_buffer.begin();} // /*.begin()返回_buffer开始的迭代器，&再返回首字母的地址

        //获取当前写入位置地址 
        char *GetWritePosition() {return Begin()+_writer_idx;} //起始位置加上写入位置，就是写入地址 

        //获取当前读取位置地址
        char *GetReadPosition() {return Begin()+_reader_idx;} //起始地址加上读取位置，就是读取地址 

        //获取前沿空间大小，就是写入位置的后面
        // _buffer.size():[ [   ] [<-_reader+idx  _writer_idx->] [  前沿空间  ] ]
        uint64_t GetTailIdleSize() {return _buffer.size()-_writer_idx;} 
        
        //获取后沿空间大小，就是读取位置的前面
        // _buffer.size():[ [  后沿空间  ] [<-_reader+idx  _writer_idx->] [   ] ]
        uint64_t GetHeadIdleSize() {return _reader_idx;}
        
        //将写入位置向右移动指定长度
        void MoveWriteOffset(uint64_t len)
        {
            assert(GetTailIdleSize()>=len); //我们确保写入的数据小于等于后沿空间
            _writer_idx+=len;
        }
        
        //将读取位置向右移动指定长度
        void MoveReadOffset(uint64_t len)
        {
            if(len==0) return ;
            assert(GetReadAbleSize()>=len); //我们确保可读数据小于等于读取长度
            _reader_idx+=len;
        }

        //确保可写空间足够(移动+扩容)          Begin
        // -----—————rsz—————-------           ——————rsz—————----------- 
        //      |           |         -->      |            |
        // _reader_idx  _writer.idx        _reader_idx  _writer.idx
        void EnsureWriteAbleSize(uint64_t len)
        {
            if(GetTailIdleSize()>=len) {return ;} //如果末尾空间足够直接返回
            else if(len<=GetTailIdleSize()+GetHeadIdleSize()) //如果末尾不够，加上前面的空间够，拷贝数据到开始位置
            {
                //将数据移动到开始的位置
                uint64_t rsz=GetReadAbleSize(); //先得到可读的数据大小，就是数据的大小
                //copy(起始地址，末尾地址，要拷贝的新的位置的地址)
                std::copy(GetReadPosition(),GetReadPosition()+rsz,Begin()); //把数据拷贝到起始位置
                _reader_idx=0; //读偏移设置为0
                _writer_idx=rsz; //写偏移设置为可读数据量的大小
            }
            else //总体空间不够，我们需要进行扩容，不移动数据，直接给空间
            {
                DBG_LOG("RESIZE %ld", _writer_idx + len);
                _buffer.resize(_writer_idx+len);
            }
        }

        //确保有可读空间，且获取可读空间大小
        uint64_t GetReadAbleSize() {return _writer_idx-_reader_idx;} //可读数据大小 = 写偏移 - 读偏移

        //写入数据
        void Write(const void *data, uint64_t len)
        {
            //1.确保有足够的空间拷贝len大小的数据
            if(len==0) return ;
            EnsureWriteAbleSize(len);
            //2.将内容拷贝进去，我们一个字节一个字节的拷贝
            const char *d=(const char*)data;
            std::copy(d,d+len,GetWritePosition());
        }

        //写入数据并且进行地址偏移
        void WriteAndPush(const void *data, uint64_t len)
        {
            Write(data,len);
            MoveWriteOffset(len);
        }

        //写入string类型数据
        void WriteString(const std::string &data)
        {
            return Write(data.c_str(),data.size());
        }

        //写入string类型数据并且偏移地址
        void WriteStringAndPush(const std::string &data)
        {
            WriteString(data);
            MoveWriteOffset(data.size());
        }

        //写入buffer类型数据
        void WriteBuffer(Buffer &data)
        {
            return Write(data.GetReadPosition(),data.GetReadAbleSize());
        }

        //写入buffer类型数据并且偏移地址
        void WriteBufferAndPush(Buffer &data)
        {
            WriteBuffer(data);
            MoveWriteOffset(data.GetReadAbleSize());
        }
        
        //读取数据
        void Read(void *buf, uint64_t len)
        {
            assert(len<=GetReadAbleSize()); //拷贝的数据要小于等于可读数据
            //我们将缓冲区的数据拷贝进入buf
            std::copy(GetReadPosition(),GetReadPosition()+len,(char*)buf);
        }

        //读取数据并且进行地址偏移
        void ReadAndPop(void *buf,uint64_t len)
        {
            Read(buf,len);
            MoveReadOffset(len);
        }

        //读取string类型数据
        std::string ReadAsString(uint64_t len)
        {
            //要求获取的数据大小必须小于可读数据大小
            assert(len<=GetReadAbleSize());
            std::string str;
            str.resize(len);
            Read(&str[0],len);
            return str;
        }

        //读取string类型数据并且偏移地址
        std::string ReadAsStringAndPop(uint64_t len)
        {
            assert(len<=GetReadAbleSize());
            std::string str=ReadAsString(len);
            MoveReadOffset(len);
            return str;
        }

        //获取一行数据
        char *FindCRLF()
        {
            // 长度为GetReadAbleSize()的内存区域中查找换行符'\n'
            char *res=(char*)memchr(GetReadPosition(),'\n',GetReadAbleSize());
            return res;
        }

        //通常使用获取一行数据
        std::string GetLine()
        {
            char *pos=FindCRLF();
            if(pos==NULL)
            {
                return "";
            }
            //+1为了将换行符也取出来
            return ReadAsString(pos-GetReadPosition()+1);
        }

        //获取一行数据并且进行地址偏移
        std::string GetLineAndPop()
        {
            std::string str=GetLine();
            MoveReadOffset(str.size());
            return str;
        }

        //清理缓冲区
        void Clear()
        {
            //直接将写入和读取偏移量设置为0即可
            _writer_idx=0;
            _reader_idx=0;
        }
};

//套接字Socket类实现
//通过创建网络套接字实现服务端和客户端之间的通信连接，并且进行数据的发送和接受
#define MAX_LISTEN 1024 //最大监听数
class Socket
{
    private:
        int _sockfd; //套接字的文件描述符
    
    public:
        //创建套接字
        //绑定地址信息
        //开始监听
        //向服务器发起连接
        //获取新连接
        //接受数据
        //发送数据
        //关闭套接字
        //创建一个服务端连接
        //创建一个客户端连接
        //设置套接字选项，开启地址端口重用
        //设置套接字阻塞属性，设置为非阻塞

        //Socket类的默认构造函数
        Socket():_sockfd(-1) {}

        //显示构造函数
        Socket(int fd):_sockfd(fd) {}

        //析构函数，关闭套接字
        ~Socket() {Close();}

        //返回套接字文件描述符
        int Fd() {return _sockfd;}

        //创建套接字，成功返回true
        bool Create()
        {
            // int socket(int domain, int type, int protocol)
            //创建一个套接字，指定地址族(IPV4 IPV6)，套接字类型(TCP UDP)，协议
            _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if(_sockfd<0)
            {
                ERR_LOG("CREATE SOCKET FAILED!");
                return false;
            }
            return true;
        }

        //绑定地址信息，绑定套接字和服务器ip地址和端口号，成功返回true
        bool Bind(const std::string &ip, uint16_t port)
        {
            struct sockaddr_in addr;
            addr.sin_family=AF_INET; //绑定地址族
            addr.sin_port=htons(port); //绑定端口
            addr.sin_addr.s_addr=inet_addr(ip.c_str()); //绑定IP地址转换的网络字节序
            socklen_t len=sizeof(struct sockaddr_in); //保存长度
            // int bind(int sockfd, struct sockaddr*addr, socklen_t len);
            int ret = bind(_sockfd, (struct sockaddr*)&addr, len); //将套接字_sockfd与地址信息绑定起来
            if(ret<0)
            {
                ERR_LOG("BIND ADDRESS FAILED!");
                return false;
            }
            return true;
        }

        //开始监听
        bool Listen(int backlog=MAX_LISTEN)
        {
            // int listen(int backlog)
            int ret = listen(_sockfd, backlog); //对套接字_sockfd进行监听操作，最大监听数为MAX_LISTEN
            if(ret<0)
            {
                ERR_LOG("SOCKET LISTEN FAILED!");
                return false;
            }
            return true;
        }
        
        //客户端向服务器发起连接
        bool Connect(const std::string &ip, uint16_t port)
        {
            struct sockaddr_in addr;
            addr.sin_family=AF_INET; //绑定地址族
            addr.sin_port=htons(port); //绑定端口
            addr.sin_addr.s_addr=inet_addr(ip.c_str()); //绑定IP地址转换的网络字节序
            socklen_t len=sizeof(struct sockaddr_in); //保存长度
            // int connect(int sockfd, struct sockaddr*addr, socklen_t len);
            int ret = connect(_sockfd, (struct sockaddr*)&addr, len); //将套接字_sockfd与服务器进行连接
            if(ret<0)
            {
                ERR_LOG("CONNECT SERVER FAILED!");
                return false;
            }
            return true;
        }

        //获取新连接
        int Accept()
        {
            // int accept(int sockfd, struct sockaddr *addr, socklen_t *len);
            int newfd = accept(_sockfd, NULL, NULL); //accept()函数接受新的连接请求
            if(newfd<0)
            {
                ERR_LOG("SOCKET ACCEPT FAILED!");
                return -1;
            }            
            return newfd;
        }

        //接受数据
        ssize_t Recv(void *buf, size_t len, int flag=0)
        {
            // ssize_t recv(int sockfd, void *buf, size_t len, int flag);
            //套接字文件描述符_sockfd，缓冲区指针buf，接收的最大字节数len，可选标志flag
            ssize_t ret = recv(_sockfd, buf, len, flag);
            if(ret<=0)
            {
                //EAGAIN 当前socket的接收缓冲区中没有数据了，在非阻塞的情况下才会有这个错误
                //EINTR  表示当前socket的阻塞等待，被信号打断了，
                if (errno == EAGAIN || errno == EINTR) 
                {
                    return 0;//表示这次接收没有接收到数据
                }
                ERR_LOG("SOCKET RECV FAILED!");
                return -1;
            }
            return ret; //实际接收的数据长度        
        }

        //非阻塞接受数据
        ssize_t NonBlockRecv(void *buf, size_t len) 
        {
            return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接收为非阻塞。
        }

        //发送数据
        ssize_t Send(const void *buf, size_t len, int flag=0)
        {
            // ssize_t send(int sockfd, void *data, size_t len, int flag);
            //套接字文件描述符_sockfd，缓冲区指针buf，接收的最大字节数len，可选标志flag
            ssize_t ret = send(_sockfd, buf, len, flag);
            if(ret<0)
            {
                if(errno==EAGAIN||errno==EINTR)
                {
                    return 0;
                }
                ERR_LOG("SOCKET SEND FAILED!");
                return -1;
            }            
            return ret; //实际发送的数据长度
        }

        //非阻塞发送数据
        ssize_t NonBlockSend(void *buf, size_t len) 
        {
            if(len==0) return 0;
            return Send(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前发送为非阻塞。
        }

        //关闭套接字
        void Close()
        {
            if(_sockfd!=-1)
            {
                close(_sockfd);
                _sockfd=-1;
            }
        }

        //创建一个服务端连接
        bool CreateServer(uint16_t port, const std::string &ip="0.0.0.0", bool block_flag=false)
        {
            //1. 创建套接字，2. 设置非阻塞，3. 绑定地址，4. 开始监听，5. 启动地址重用
            if(Create()==false) return false;
            if(block_flag) NonBlock();
            if(Bind(ip,port)==false) return false;
            if(Listen()==false) return false;
            ReuseAddress();
            return true;
        }

        //创建一个客户端连接
        bool CreateClient(uint16_t port, const std::string &ip)
        {
            //1. 创建套接字，2.连接服务器
            if(Create()==false) return false;
            if(Connect(ip,port)==false) return false;
            return true;
        }

        //设置套接字选项，开启地址端口重用
        void ReuseAddress()
        {
            // int setsockopt(int fd, int leve, int optname, void *val, int vallen)
            //套接字文件描述符_sockfd，选项级别level，选项名称optname，存储选项指针val，选项值的大小vallen
            int val = 1;
            setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(int)); //SO_REUSEADDR：允许地址重用
            val = 1;
            setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)&val, sizeof(int)); //SO_REUSEPORT：允许端口重用
        }

        //设置套接字阻塞属性，设置为非阻塞
        void NonBlock()
        {
            //int fcntl(int fd, int cmd, ...  arg );
            int flag = fcntl(_sockfd, F_GETFL, 0);
            fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
            //通过调用fcntl(_sockfd, F_GETFL, 0)获取当前文件描述符的标志位，存储在变量flag中
            //使用F_SETFL标志将O_NONBLOCK标志添加到flag中，表示将套接字设置为非阻塞模式
            //再次调用fcntl(_sockfd, F_SETFL, flag)来将新的标志位设置回套接字的文件描述符
        }
}; 

//事件管理Channel类的实现
//我们创建Channel类实现对描述符的监控操作管理
class Poller;
class EventLoop;
class Channel
{
    private:
        int _fd; //文件描述符
        EventLoop *_loop; //EventLoop
        //Poller *_poller; //将我们的Poller模块和Channel模块进行整合 
        uint32_t _events; //当前需要监控的事件
        uint32_t _revents; //当前连接触发的事件
        using EventCallback = std::function<void()>; //定义一个函数包装器类型
        EventCallback _read_callback; //可读事件被触发的回调函数
        EventCallback _write_callback; //可写事件被触发的回调函数
        EventCallback _error_callback; //错误事件被触发的回调函数
        EventCallback _close_callback; //连接断开事件被触发的回调函数
        EventCallback _event_callback; //任意事件被触发的回调函数

    public:
        //当前是否可读
        //当前是否可写
        //启动读事件监控
        //启动写事件监控
        //关闭读事件监控
        //关闭写事件监控
        //关闭所有事件监控
        //移除监控

        //构造函数
        Channel(EventLoop *loop,int fd):_fd(fd),_events(0),_revents(0),_loop(loop) {}

        //获取文件描述符
        int Fd() {return _fd;}

        //获取想要监控的事件
        uint32_t Events() { return _events; }

        //将实际就绪的事件设置进来
        void SetREvents(uint32_t events) {_revents = events;}

        //设置可读事件的回调
        void SetReadCallback(const EventCallback &cb) { _read_callback = cb; }
        
        //设置可写事件的回调
        void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
        
        //设置错误事件的回调
        void SetErrorCallback(const EventCallback &cb) { _error_callback = cb; }
        
        //设置断开事件的回调
        void SetCloseCallback(const EventCallback &cb) { _close_callback = cb; }
        
        //设置任意事件的回调
        void SetEventCallback(const EventCallback &cb) { _event_callback = cb; }

        //当前是否可读
        bool ReadAble() { return (_events & EPOLLIN); } //是否监控了可读事件

        //当前是否可写
        bool WriteAble() { return (_events & EPOLLOUT); } //是否监控的可写事件

        //启动读事件监控
        void EnableRead() { (_events |= EPOLLIN); Update(); }

        //启动写事件监控
        void EnableWrite() { (_events |= EPOLLOUT); Update(); }

        //关闭读事件监控
        void DisableRead() { (_events &= ~EPOLLIN); Update(); }

        //关闭写事件监控
        void DisableWrite() { (_events &= ~EPOLLOUT); Update(); }

        //关闭所有事件监控
        void DisableAll() { _events = 0; Update(); }

        //移除监控
        void Remove();

        //更新事件
        void Update();

        //事件处理，一旦连接触发了事件，就调用这个函数，自己触发了什么事件如何处理自己决定
        void HandleEvent()
        {
            //如果三种情况中有一种情况被触发了，就触发可读事件回调
            if((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
            {
                //不管任何事件，都调用的回调函数
                //if(_event_callback) _event_callback(); 

                if(_read_callback) _read_callback();
            }

            //有可能是否连接的操作一次只处理一个，安全第一
            if(_revents & EPOLLOUT) //如果可写情况触发，就触发可写事件回调
            {
                //不管任何事件，都调用的回调函数
                //if(_event_callback) _event_callback(); //放在事件处理完毕后调用，刷新活跃度

                if(_write_callback) _write_callback();
            }
            else if(_revents & EPOLLERR) //如果描述符出错，就调用错误回调
            {
                //不管任何事件，都调用的回调函数
                //if(_event_callback) _event_callback(); 

                if(_error_callback) _error_callback(); //一旦出错就释放连接，没有必要调用任意回调了，可以放在前面
            }
            else if(_revents & EPOLLHUP) //关闭连接
            {
                //不管任何事件，都调用的回调函数
                //if(_event_callback) _event_callback(); 

                if(_close_callback) _close_callback();
            }
            if(_event_callback) _event_callback();
        }
};


//描述符事件监控Poller类实现
//通过封装epoll操作实现我们对描述符的IO事件操作
#define MAX_EPOLLEVENTS 1024
class Poller
{
    private:
        int _epfd; //epoll文件描述符
        struct epoll_event _evs[MAX_EPOLLEVENTS]; //epoll事件监控数组
        std::unordered_map<int, Channel*> _channels;

    private:
        //封装私有的epoll操作
        //使用epoll函数对channel进行不同的epoll操作，根据op命令
        void Update(Channel *channel, int op)
        {
            // int epoll_ctl(int epfd, int op,  int fd,  struct epoll_event *ev);
            // fd：要操作的监控事件的文件描述符
            int fd=channel->Fd(); 

            // ev：一个epoll_event结构体，用于指定要注册或修改的事件
            struct epoll_event ev;
            ev.data.fd=fd;
            ev.events=channel->Events();
            
            // epoll_ctl用于控制epoll实例，epfd：epoll实例的文件描述符
            // op：操作类型，表示要执行的操作。可选的操作类型包括：
            //  EPOLL_CTL_ADD：将指定的文件描述符添加到epoll实例中进行监视
            //  EPOLL_CTL_MOD：修改已经注册的文件描述符的事件
            //  EPOLL_CTL_DEL：从epoll实例中删除指定的文件描述符
            int ret=epoll_ctl(_epfd,op,fd,&ev);

            if(ret<0)
            {
                ERR_LOG("EPOLLCTL FAILED!");
            }
            return;
        }

        //判断一个Channel是否已经添加了事件监控
        bool HashChannel(Channel *channel)
        {
            //找到我们描述符对应的信息
            auto it=_channels.find(channel->Fd());

            if(it==_channels.end()) //没有找到返回错误
            {
                return false;
            }
            return true;
        }

    public:
        //Poller的构造函数
        Poller()
        {
            //进行epoll的创建
            _epfd=epoll_create(MAX_EPOLLEVENTS);
            if(_epfd<0)
            {
                ERR_LOG("EPOLL CREATE FAILED!");
                abort(); //退出程序
            }
        }

        //添加或者修改监控事件
        void UpdateEvent(Channel *channel)
        {
            bool ret=HashChannel(channel); //判断是否存在channel
            
            if(ret==false)
            {
                _channels.insert(std::make_pair(channel->Fd(),channel));
                return Update(channel,EPOLL_CTL_ADD); //不存在就添加
            }

            return Update(channel,EPOLL_CTL_MOD); //存在了就进行了更新
        }

        //移除监控
        void RemoveEvent(Channel *channel)
        {
            auto it=_channels.find(channel->Fd()); //找到我们要移除的事件
            if(it!=_channels.end())
            {
                _channels.erase(it); //删除监控事件
            }
            
            //移除我们的事件监控
            Update(channel,EPOLL_CTL_DEL);
        }

        //开始监控，返回所有的活跃连接
        void Poll(std::vector<Channel*> *active)
        {
            // int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
            //epoll_wait是一个用于等待epoll事件的函数，它会阻塞当前线程，直到有事件发生或者超时
            
            //epfd：epoll实例的文件描述符，即通过epoll_create函数创建的文件描述符
            //evs：一个指向epoll_event结构体数组的指针，用于存储epoll返回的事件信息
            //maxevents：evs数组的大小，表示最多可以存储多少个事件
            //timeout：超时时间，以毫秒为单位，大于0表示最长等待时间
            //如果设置为-1，则表示一直等待直到有事件发生；如果设置为0，则表示立即返回
            int nfds=epoll_wait(_epfd,_evs,MAX_EPOLLEVENTS,-1);
            if(nfds<0)
            {
                if(errno==EINTR)
                {
                    return;
                }
                ERR_LOG("EPOLL WAIT ERROR:%s\n",strerror(errno));
                abort(); //退出程序
            }

            for(int i=0;i<nfds;i++)
            {
                auto it=_channels.find(_evs[i].data.fd); //查找_channel
                assert(it!=_channels.end());
                it->second->SetREvents(_evs[i].events); //设置实际就绪的事件
                active->push_back(it->second); //放入我们的活跃事件
            }

            return;
        }
};

using TaskFunc=std::function<void()>;  //使用TaskFunc包装器函数
using ReleaseFunc=std::function<void()>; //额外的释放操作

//我们将我们的定时任务封装为一个类，便于析构函数调用我们的定时任务
class TimerTask{
    private:
        uint64_t _id; //定时器任务的id
        uint32_t _timeout; //这是定时任务的超时时间
        bool _canceled; //是否取消任务 false没有取消 true取消
        TaskFunc _task_cb; //定时器要执行的定时任务
        ReleaseFunc _release; //用于删除TimerWheel中保存的定时器对象信息
    
    public:
        //定时器的构造，定时器id，延迟时间，要执行的定时任务
        TimerTask(uint64_t id,uint32_t delay,const TaskFunc &cb) 
            :_id(id),_timeout(delay),_task_cb(cb),_canceled(false) {}

        //定时器的析构，并且执行我们的定时任务
        ~TimerTask() 
        {
            if(_canceled==false)_task_cb();
            _release();
        }

        void Cancel() {_canceled=true;} //取消我们的定时任务
        void SetRelease(const ReleaseFunc &cb) {_release=cb;}; //删除对应哈希表中的数据
        uint64_t DelayTime() {return _timeout;}; // 获取超时时间
};

//TimerWheel实现时间轮类，处理TimerTask任务
//这是我们的时间轮的类，我们将定时任务类存放在时间轮中
class TimerWheel{
    private:
        using WeakTask=std::weak_ptr<TimerTask>; //weak_ptr
        using PtrTask=std::shared_ptr<TimerTask>; //声明一个智能指针类型
        //时间轮是一个二维数组，同一个时间可能有多个定时任务要执行
        int _tick; //释放tick处的对象，走到哪里执行哪里的任务
        int _capacity; //表盘的最大数量，就是最大的延迟时间
        std::vector<std::vector<PtrTask>> _wheel; //注意存放的是PtrTask
        std::unordered_map<uint64_t,WeakTask> _timers; //id和weak_ptr对象的映射
        
        EventLoop *_loop; //_timerfd的监控
        int _timerfd; //定时器描述符，可读事件回调就是读取计时器，执行定时任务
        std::unique_ptr<Channel> _timer_channel; //管理定时器描述符的事件回调

    private:
        //删除我们哈希表中id定时任务
        void RemoveTimer(uint64_t id)
        {
            auto it=_timers.find(id); //通过迭代器我们找到id的位置
            if(it!=_timers.end())
            {
                _timers.erase(it);
            }
        }

        //创建我们的定时器描述符
        static int CreateTimerfd()
        {
            int timerfd=timerfd_create(CLOCK_MONOTONIC,0); //我们创建一个定时器
            if(timerfd<0)
            {
                ERR_LOG("timerfd_create failed\n"); //创建计时器失败
                abort();
            }
            
            //这里设置我们定时器的时间
            struct itimerspec itime;
            itime.it_value.tv_sec=1; //设置第一次的超时时间是1s
            itime.it_value.tv_nsec=0;

            itime.it_interval.tv_sec=1; //设置第一次超时后，每次间隔超时的时间
            itime.it_interval.tv_nsec=0;

            //填入参数，因为没有原来的定时器超时时间，所以设置为NULL
            timerfd_settime(timerfd,0,&itime,NULL);
            return timerfd;
        }

        //读取定时器描述符中的内容
        int ReadTimefd()
        {
            uint64_t times; //每次超时，系统都要读取8字节的数据到timerfd中
            int ret=read(_timerfd,&times,8); //从timerfd中读取数据放入times，没有数据读入就会阻塞，直到数据读入
            if(ret<0)
            {
                ERR_LOG("read timefd failed\n");
                abort();
            }
            return times;
        }

        //执行我们的定时任务，每秒进行一次
        void RunTimerTask()
        {
            _tick=(_tick+1)%_capacity;
            _wheel[_tick].clear(); //清空指定位置的数组，就会吧数组中所有管理定时器对象的share_ptr释放掉
        }

        //时间到了，读取我们的timerfd并且执行定时任务
        void OnTime()
        {
            //根据实际超时的次数，执行对应的超时任务
            int times = ReadTimefd();
            for (int i = 0; i < times; i++) 
            {
                RunTimerTask();
            }
        }

        //添加定时任务
        void TimerAddInLoop(uint64_t id,uint32_t delay,const TaskFunc &cb)
        {
            PtrTask pt(new TimerTask(id,delay,cb)); //新建一个定时任务的智能指针类
            pt->SetRelease(std::bind(&TimerWheel::RemoveTimer,this,id)); //释放对象，要传入隐藏的this指针
            int pos=(_tick+delay)%_capacity; //取模
            _wheel[pos].push_back(pt); //添加到时间轮后的超时位置
            _timers[id]=WeakTask(pt); //针对ptr示例化一个weak_ptr
        }

        //刷新延时定时任务
        void TimerRefreshInLoop(uint64_t id) 
        {
            //通过保存的定时器对象的weak_ptr构造一个shared_ptr，添加到轮子中
            auto it=_timers.find(id); //通过迭代器我们找到id的位置
            if(it==_timers.end())
            {
                return ; //没有找到定时任务
            }

            PtrTask pt=it->second.lock(); //lock用来获取weak_ptr管理对象对应的shared_ptr
            int delay=pt->DelayTime(); //获取超时时间
            int pos=(_tick+delay)%_capacity; //取模
            _wheel[pos].push_back(pt); //添加到时间轮后的超时位置
        }

        //取消对应id的定时任务
        void TimerCancelInLoop(uint64_t id) 
        {
            auto it=_timers.find(id); //通过迭代器我们找到id的位置
            if(it==_timers.end())
            {
                return ; //没有找到定时任务
            }
            PtrTask pt=it->second.lock();
            if(pt) pt->Cancel();
        }

    public:
        //初始化我们的时间轮
        TimerWheel(EventLoop *loop):_capacity(60),_tick(0),_wheel(_capacity),_loop(loop),
            _timerfd(CreateTimerfd()),_timer_channel(new Channel(_loop,_timerfd))
        {
            _timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTime,this));
            _timer_channel->EnableRead(); //启动读事件监控
        }
        
        //很多的任务都涉及到对连接的操作，需要考虑线程安全
        //定时器中有_timers成员，定时器信息的操作有可能在多个线程中进行，因此考虑线程安全
        //加锁影响效率，不加锁，我们就把对定期所有的操作，都放在一个线程中执行
        void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb);

        //刷新延时定时任务
        void TimerRefresh(uint64_t id);

        //取消对应id的定时任务
        void TimerCancel(uint64_t id);

        //查找是否存在定时器任务，这个接口存在线程安全问题
        //这个接口不能被外界使用者调用，只能在模块内，在对应的EventLoop线程内执行
        bool HasTimer(uint64_t id)
        {
            auto it=_timers.find(id); //通过迭代器我们找到id的位置
            if(it==_timers.end())
            {
                return false; //没有找到定时任务
            }

            return true;
        }
};

//EventLoop实现对于事件监控，以及模块处理
//主要这个模块和线程是一一对应的，eventloop的处理流程，1.在线程中对描述符进行事件监控
//2.有描述符就绪进行事件处理 3.所有的就绪事件处理完了，再去任务队列中的任务一一执行
class EventLoop
{
    private:
        using Functor=std::function<void()>; //包装器
        std::thread::id _thread_id; //线程ID，判断要执行的操作是否在线程池中，不在就放入任务池
        int _event_fd; //eventfd唤醒IO事件监控有可能导致的阻塞
        std::unique_ptr<Channel> _event_channel; //通过_event_channel管理我们的_event_fd
        Poller _poller; //对事件进行监控的类对象
        std::vector<Functor> _tasks; //任务池，存放由线程带来的执行任务
        std::mutex _mutex; //互斥锁，用于保障任务池的线程安全
        TimerWheel _timer_wheel; //定时器模块
    
    public:
        //执行任务池中的所有任务
        void RunAllTask()
        {
            std::vector<Functor> functor;
            //进行加锁保护线程安全，在作用域内加锁，在作用域外会解锁
            {
                std::unique_lock<std::mutex> _lock(_mutex);
                _tasks.swap(functor); //_tasks和functor进行交换，这样functor内就是我们要执行的任务
            }

            for(auto &f:functor) 
            {
                f(); //执行任务池中的所有任务
            }

            return ;
        }

        //创建我们的EventFd
        static int CreateEventFd()
        {
            // 创建一个能被用户应用程序用于时间等待唤醒机制的eventfd对象，关闭文件描述符|非阻塞
            int efd=eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
            if(efd<0)
            {
                ERR_LOG("Create eventfd failed!");
                abort(); //程序退出
            }

            return efd;
        }

        //读取Eventfd中的数据
        void ReadEventfd()
        {
            // 用于在不同的线程或进程之间传递事件通知
            uint64_t res=0;
            int ret=read(_event_fd,&res,sizeof(res));
            if(ret<0)
            {
                if(errno==EINTR || errno== EAGAIN) //信号打断，无数据可读
                {
                    return ;
                }
                ERR_LOG("Read Eventfd Failed!");
                abort();
            }

            return ;
        }

        //唤醒我们的EventFd
        void WeakUpEventFd()
        {
            // 向事件文件描述符写入数据，以唤醒等待在该事件文件描述符上的读取操作
            uint64_t res=1;
            int ret=write(_event_fd,&res,sizeof(res));
            if(ret<0)
            {
                if(errno==EINTR) //信号打断
                {
                    return ;
                }
                ERR_LOG("Read Eventfd Failed!");
                abort();
            }

            return ;
        }

    public:
        //构造函数 
        EventLoop():_thread_id(std::this_thread::get_id()),
                    _event_fd(CreateEventFd()),
                    _event_channel(new Channel(this,_event_fd)),
                    _timer_wheel(this)
        {
            //给eventfd添加可读事件回调函数，读取eventfd事件通知次数
            _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd,this));
            //启动eventfd的读事件监控
            _event_channel->EnableRead();
        }

        //事件监控->就绪事件处理->执行任务
        void Start()
        {
            while(1)
            {
                std::vector<Channel*> actives;
                _poller.Poll(&actives); //对事件进行监控

                for(auto &channel:actives)
                {
                    channel->HandleEvent(); //回调进行事件的处理
                }

                RunAllTask(); //执行任务
            }
        }

        //判断当前线程是否是EventLoop对应的线程
        bool IsInLoop()
        {
            return (_thread_id==std::this_thread::get_id()); 
        }

        //断言某一个操作一定在线程中
        void AssertInLoop()
        {
            assert(_thread_id==std::this_thread::get_id()); 
        }

        //判断要执行的任务是否在当前线程中，如果是直接执行，不是就压入队列
        void RunInLoop(const Functor &cb)
        {
            if(IsInLoop())
            {
                return cb(); //如果在线程里面我们就直接调用
            }

            return QueueInLoop(cb); //不在线程里面的话，我们将操作压入任务池中
        }

        //将操作压入任务池
        void QueueInLoop(const Functor &cb)
        {
            //加锁
            {
                std::unique_lock<std::mutex> _lock(_mutex);
                _tasks.push_back(cb); //将我们的任务压到任务池中
            }

            //唤醒有可能因为没有事件就绪，而导致的epoll阻塞
            //就是给eventfd写入一个数据，event就会触发可读事件
            WeakUpEventFd();
        }

        //添加或者修改描述符的事件监控
        void UpdateEvent(Channel *channel)
        {
            return _poller.UpdateEvent(channel); 
        }

        //移除描述符的监控
        void RemoveEvent(Channel *channel)
        {
            return _poller.RemoveEvent(channel);
        }

        //添加一个定时器任务
        void TimerAdd(uint16_t id,uint32_t delay,const TaskFunc &cb)
        {
            return _timer_wheel.TimerAdd(id,delay,cb);
        }

        //刷新定时器任务
        void TimerRefresh(uint64_t id)
        {
            return _timer_wheel.TimerRefresh(id);
        }

        //取消定时器任务 
        void TimerCancel(uint64_t id)
        {
            return _timer_wheel.TimerCancel(id);
        }

        //是否有定时器任务的存在
        bool HasTimer(uint64_t id)
        {
            return _timer_wheel.HasTimer(id);
        }
};

//LoopThread模块实现将EventLoop模块和线程模块一一对应起来
class LoopThread
{
    private:
        //用于实现_loop获取的同步关系，避免线程创建了，但是_loop还没有实例化之前去获取_loop
        std::mutex _mutex; //互斥锁
        std::condition_variable _cond; //条件变量
        EventLoop *_loop; //EventLoop指针变量，这个对象需要再线程中实例化
        std::thread _thread; //EventLoop对应的线程
    
    private:
        //示例化EventLoop对象，唤醒_cond上可能阻塞的线程，并且开始运行EventLoop模块的功能
        void ThreadEntry()
        {
            EventLoop loop;
            {
                std::unique_lock<std::mutex> lock(_mutex); //加锁
                _loop=&loop;
                _cond.notify_all(); //唤醒线程
            }
            loop.Start();
        }

    public:
        //创建线程，设定线程入口函数
        LoopThread():_loop(NULL),_thread(std::thread(&LoopThread::ThreadEntry,this)){}

        //返回当前线程关联的EventLoop对象指针
        EventLoop *GetLoop()
        {
            EventLoop *loop=NULL;
            {
                std::unique_lock<std::mutex> lock(_mutex); //加锁
                _cond.wait(lock,[&](){ return _loop!=NULL; }); //loop为空，就一直循环阻塞，等待被唤醒
                loop=_loop;
            }
            return loop;
        }
};

//LoopThreadPool模块实现
//LoopThreadPool实现对所有的LoopThread进行管理和分配
class LoopThreadPool
{
    private:
        int _thread_count; //从属线程的数量
        int _next_loop_idx; //loop索引
        EventLoop *_baseloop; //主EventLoop，从属线程数量为0，则所有操作都在baseloop中进行
        std::vector<LoopThread*> _threads; //保存所有的LoopThread对象
        std::vector<EventLoop*> _loops; //从属线程数量大于0，从_loops中进行线程EventLoop分配
    
    public:
        //构造函数
        LoopThreadPool(EventLoop *baseloop):_thread_count(0),_next_loop_idx(0),_baseloop(baseloop) {}

        //设置线程数量
        void SetThreadCount(int count)
        {
            _thread_count=count;
        }

        //创建所有的从属线程
        void Create()
        {
            if(_thread_count>0)
            {
                _threads.resize(_thread_count);
                _loops.resize(_thread_count);
                for(int i=0;i<_thread_count;i++)
                {
                    _threads[i]=new LoopThread();
                    _loops[i]=_threads[i]->GetLoop();
                }
            }
            return ;
        }

        //获取下一个EventLoop
        EventLoop *NextLoop()
        {
            if(_thread_count==0)
            {
                return _baseloop;
            }
            _next_loop_idx=(_next_loop_idx+1)%_thread_count; 
            return _loops[_next_loop_idx];
        }
};


//any类的实现
//我们使用多态实现any类型的实现，保存父类holder的指针，子类对象placeholder继承父类
//我们将接受到的不同类型的数据使用模版保存在子类中
class Any
{
    private:
        //这是我们的父类holder
        class holder 
        {
            public:
                //设置为纯虚函数确保不会被实例化，也为了实现虚函数的重写
                virtual const std::type_info& type()=0; //返回子类成员类型
                virtual holder *clone()=0; //克隆父类对象函数
                virtual ~holder(){} //父类的析构函数
        };

        //不同类型的子类对象placeholder，继承自父类holder
        template<class T>
        class placeholder:public holder
        {
            public:
                placeholder(const T&val):_val(val){} //这是子类的构造函数

                //获取子类对象保存的数据类型
                virtual const std::type_info& type() {return typeid(T);}
                
                //针对当前的对象本身，克隆一个新的子类对象
                virtual holder *clone() {return new placeholder(_val);}

            public:
                T _val; //_val就是我们接受到的数据类型
        };
    
    private:
        holder *_content; //any保存父类对象的指针，以便实现多态

    public:
        Any():_content(NULL) {} //Any类的构造函数

        template<class T>
        Any(const T &val):_content(new placeholder<T>(val)) {} //使用子类对象构造Any类

        Any(const Any &other)
        :_content(other._content?other._content->clone():NULL) {} //使用其他Any类对象构造Any类

        ~Any() {delete _content;} //Any的析构函数

        Any &swap(Any &other) //交换函数
        {
            std::swap(_content,other._content);
            return *this;
        }

        //重要，返回子类对象保存的数据的指针
        template<class T>
        T *get()
        {
            //获取的数据类型必须和保存的一致
            assert(typeid(T)==_content->type());
            return &(((placeholder<T>*)_content)->_val); //父类指针强制类型转换子类指针
        }

        //对于子类对象的赋值运算符的重载函数
        template<class T>
        Any& operator=(const T&val)
        {
            //为val构造一个临时的通用容器，然后与当前容器自身进行指针交换
            //临时对象释放的时候，原先保存的数据也就被释放
            Any(val).swap(*this);
            return *this;
        }

        //对于Any类对象的赋值运算符的重载函数
        Any& operator=(const Any &other)
        {
            Any(other).swap(*this);
            return *this;
        }
};


//Connection类实现对连接进行全方位的管理，操作所有对通信的连接
//需要管理：套接字，连接事件，缓冲区，协议上下文，回调函数(连接，数据，关闭连接，任意事件)

//使用枚举变量表示连接的状态
typedef enum { 
    DISCONNECTED, //DISCONNECTED -- 连接关闭状态
    CONNECTING, //CONNECTING -- 连接建立成功-待处理状态
    CONNECTED, //CONNECTED -- 连接建立完成，各种设置已完成，可以通信的状态
    DISCONNECTING //DISCONNECTING -- 待关闭状态
}ConnStatu;

class Connection;
using PtrConnection=std::shared_ptr<Connection>;
class Connection : public std::enable_shared_from_this<Connection>
{
    private:
        uint64_t _conn_id;  // 连接的唯一ID，便于连接的管理和查找
        //uint64_t _timer_id;   //定时器ID，必须是唯一的，这块为了简化操作使用conn_id作为定时器ID
        int _sockfd;        // 连接关联的文件描述符
        bool _enable_inactive_release;  // 连接是否启动非活跃销毁的判断标志，默认为false
        EventLoop *_loop;   // 连接所关联的一个EventLoop
        ConnStatu _statu;   // 连接状态
        Socket _socket;     // 套接字操作管理
        Channel _channel;   // 连接的事件管理
        Buffer _in_buffer;  // 输入缓冲区---存放从socket中读取到的数据
        Buffer _out_buffer; // 输出缓冲区---存放要发送给对端的数据
        Any _context;       // 请求的接收处理上下文

        //这四个回调函数，是让服务器模块来设置的（其实服务器模块的处理回调也是组件使用者设置的）
        //换句话说，这几个回调都是组件使用者使用的
        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&, Buffer *)>;
        using ClosedCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        ConnectedCallback _connected_callback; //用户决定的连接建立成功回调函数
        MessageCallback _message_callback; //用户决定的数据处理函数
        ClosedCallback _closed_callback; //用户决定的关闭连接回调函数
        AnyEventCallback _event_callback; //用户决定的任意事件的回调函数
        //组件内的连接关闭回调，组件内设置的，因为服务器组件内会把所有的连接管理起来，一旦某个连接要关闭
        //就应该从管理的地方移除掉自己的信息
        ClosedCallback _server_closed_callback; //关闭Connection组件自己的回调函数

    private:
        //五个channel的事件回调函数

        //设置给channel的可读事件回调函数
        //描述符可读事件触发后调用的函数，接收socket数据放到接收缓冲区中，然后调用_message_callback
        void HandleRead()
        {
            //1.接收socket的数据，放到缓冲区
            char buf[65536];
            ssize_t ret=_socket.NonBlockRecv(buf,65535); //如果缓冲区没有数据，可能会阻塞，我们使用非阻塞接受数据
            if(ret<0)
            {
                //出错了，不能直接关闭连接，应该看缓冲区还有没有数据要处理
                return ShutdownInLoop(); //非直接关闭接口
            }
            //else if(ret==0)
            //{
            //    return ; //没有接收到数据，直接返回，不是连接断开
            //}
            
            _in_buffer.WriteAndPush(buf,ret); //向输入缓冲区写入数据，顺便将写偏移向后移动

            //2.调用message_callback进行业务处理
            if(_in_buffer.GetReadAbleSize()>0) //如果可读数据大于0，就进行我们的数据处理
            {
                //shared_from_this，从当前对象自身获取自身的shared_ptr管理对象
                return _message_callback(shared_from_this(),&_in_buffer);
            }
        }

        //设置给channel的可写事件回调函数
        //描述符可写事件触发后调用的函数，将发送缓冲区中的数据进行发送
        void HandleWrite() 
        {
            //_out_buffer中保存的数据就是我们要发送的数据
            ssize_t ret=_socket.NonBlockSend(_out_buffer.GetReadPosition(),_out_buffer.GetReadAbleSize());
            if(ret<0)
            {
                //发送数据失败，就该关闭连接了
                if(_in_buffer.GetReadAbleSize()>0) //如果可读数据大于0，就进行我们的数据处理
                {
                    //shared_from_this，从当前对象自身获取自身的shared_ptr管理对象
                    _message_callback(shared_from_this(),&_in_buffer);
                }
                return Release(); //这时候就是实际的关闭释放操作
            }

            //不要忘记读偏移向后移动
            _out_buffer.MoveReadOffset(ret); 
            
            if(_out_buffer.GetReadAbleSize()==0) //缓冲区数据为0
            {
                _channel.DisableWrite(); //没有数据待发送，关闭写事件监控
            
                //如果当前是连接待关闭状态，则有数据，发送完数据释放连接，没有数据直接释放
                if(_statu==DISCONNECTING) 
                {
                    return Release(); //连接待关闭状态没有数据，就直接释放
                }
            }
            return ;
        }

        //设置给channel的关闭事件回调函数
        //描述符触发挂断事件
        void HandleClose()
        {
            //一旦连接挂断了，套接字就什么也做不了，因此有数据待处理就处理一下就行，完毕关闭连接
            //发送数据失败，就该关闭连接了
            if(_in_buffer.GetReadAbleSize()>0) //如果可读数据大于0，就进行我们的数据处理
            {
                //shared_from_this，从当前对象自身获取自身的shared_ptr管理对象
                _message_callback(shared_from_this(),&_in_buffer);
            }

            return Release(); //这时候就是实际的关闭释放操作
        }

        //设置给channel的错误事件回调函数
        //描述符触发出错事件
        void HandleError()
        {
            return HandleClose(); //出错了就直接挂断
        }

        //设置给channel的任意事件回调函数
        //描述符触发任意事件: 1.刷新连接的活跃度，延迟定时销毁任务  2.调用组件使用者的任意事件回调
        void HandleEvent() 
        {
            if(_enable_inactive_release==true) //如果非活跃连接释放启动了
            {
                //我们就要刷新我们的活跃度
                _loop->TimerRefresh(_conn_id);
            }
            if(_event_callback) //调用任意事件回调
            {
                _event_callback(shared_from_this());
            }
        }

        //连接获取之后，所处的状态下要进行各种设置
        //1.启动读监控 2.调用回调函数
        void EstablishedInLoop()
        {
            //1.修改连接状态 
            assert(_statu==CONNECTING); //当前的状态必须一定是上层的半连接状态
            _statu=CONNECTED; //当前函数执行完毕，则连接进入已完成连接状态

            //2.启动读事件监控
            //启动读事件监控就有可能会立即触发读事件，如果这时候启动了非活跃连接销毁
            _channel.EnableRead();

            //3.调用回调函数
            if(_connected_callback) _connected_callback(shared_from_this());
        }

        //这个接口才是实际的释放接口
        void ReleaseInLoop()
        {
            //1.修改连接状态，将其置为DISCONNECTED
            _statu=DISCONNECTED;

            //2.移除连接的事件监控
            _channel.Remove();

            //3.关闭描述符
            _socket.Close();

            //4.如果当前定时器队列中还有定时销毁任务，则取消任务
            if(_loop->HasTimer(_conn_id)) CancelInactiveReleaseInLoop();

            //5.调用关闭回调函数，避免先移除服务器管理的连接信息导致Connection被释放，再去处理会出错，因此先调用用户的回调函数
            if(_closed_callback) _closed_callback(shared_from_this());
            //移除服务器内部管理的连接信息
            if(_server_closed_callback) _server_closed_callback(shared_from_this());
        }

        //这个接口并不是实际的发送接口，而只是把数据放到了发送缓冲区，启动了可写事件监控
        //实际的数据发送在HandleRead中 
        void SendInLoop(Buffer &buf)
        {
            //如果是连接关闭状态，什么都不做
            if(_statu==DISCONNECTED) return;

            //将数据写入写缓冲区
            _out_buffer.WriteBufferAndPush(buf);

            if(_channel.WriteAble()==false)
            {
                _channel.EnableWrite(); //启动写事件监控
            }
        }

        //这个关闭操作并非实际的连接释放操作，需要判断还有没有数据待处理，待发送
        void ShutdownInLoop()
        {
            // _statu==DISCONNECTING; //设置连接为半关闭状态
            _statu=DISCONNECTING; //设置连接为半关闭状态

            //如果写入缓冲区有写入数据处理，就进行数据的写入
            if(_in_buffer.GetReadAbleSize()>0) 
            {
                if(_message_callback) _message_callback(shared_from_this(),&_in_buffer);
            }

            //要么就是写入数据的时候出错关闭，要么就是没有带发送数据，直接关闭
            //如果写入缓冲区有读取数据处理，就进行数据的写事件监控
            if(_out_buffer.GetReadAbleSize()>0) 
            {
                if(_channel.WriteAble()==false)
                {
                    _channel.EnableWrite(); //启动写事件监控
                }
            }

            //没有数据处理，直接释放连接
            if(_out_buffer.GetReadAbleSize()==0) 
            {
                Release();
            }
        }

        //启动非活跃连接超时释放
        void EnableInactiveReleaseInLoop(int sec)
        {
            //1.将判断标志设置为true
            _enable_inactive_release=true;

            //2.如果当前定时销毁任务已经存在，那就刷新延迟一下即可
            if(_loop->HasTimer(_conn_id))
            {
                return _loop->TimerRefresh(_conn_id);
            }

            //3.如果不存在定时销毁任务，则新增
            _loop->TimerAdd(_conn_id,sec,std::bind(&Connection::Release,this));
        }

        //取消非活跃连接超时释放
        void CancelInactiveReleaseInLoop()
        {
            _enable_inactive_release=false; //取消标志位
            if(_loop->HasTimer(_conn_id))
            {
                _loop->TimerCancel(_conn_id); //取消定时任务
            }
        }

        //切换，升级协议
        void UpgradeInLoop(const Any &context, 
            const ConnectedCallback &conn, 
            const MessageCallback &msg, 
            const ClosedCallback &closed, 
            const AnyEventCallback &event) 
        {
            _context=context;
            _connected_callback=conn;
            _message_callback=msg;
            _closed_callback=closed;
            _event_callback=event;
        }
    
    public:
        //构造函数
        Connection(EventLoop *loop, uint64_t conn_id, int sockfd)
            :_conn_id(conn_id), _sockfd(sockfd),
            _enable_inactive_release(false), _loop(loop), 
            _statu(CONNECTING), _socket(_sockfd),
            _channel(loop, _sockfd)
        {
            _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
            _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
            _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
            _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
            _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
        }

        //析构函数
        ~Connection()
        {
            DBG_LOG("RELEASE CONNECTION:%p", this);
        }

        //这是我们提供的公有接口，给用户使用的接口
        //提供的获取Connection类的成员变量接口
        
        //获取管理的文件描述符
        int Fd() { return _sockfd; }

        //获取连接ID
        int Id() { return _conn_id; }

        //是否处于Connection状态
        bool Connected() { return (_statu==CONNECTED); }

        //设置上下文，连接建立完成时进行调用
        void SetContext(const Any &context) { _context=context; }

        //获取上下文，返回的是指针
        Any *GetContext() { return &_context; }

        //进行回调函数的设置
        void SetConnectedCallback(const ConnectedCallback&cb) { _connected_callback = cb; }
        void SetMessageCallback(const MessageCallback&cb) { _message_callback = cb; }
        void SetClosedCallback(const ClosedCallback&cb) { _closed_callback = cb; }
        void SetAnyEventCallback(const AnyEventCallback&cb) { _event_callback = cb; }
        void SetSrvClosedCallback(const ClosedCallback&cb) { _server_closed_callback = cb; }

        //连接建立就绪后，进行channel回调设置，启动读监控，调用_connection_callback
        void Established()
        {
            _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
        }
        
        //主要的功能设计
        //1.发送数据，给用户提供的发送数据接口，把数据放到缓冲区，启动写事件监控
        //2.关闭连接，给用户提供的关闭连接接口，应该在实际释放连接之前，看看输入和输出缓冲区是否有数据处理
        //3.启动非活跃连接的超时销毁功能
        //4.取消非活跃连接的超时销毁功能
        //5.协议切换，一个连接接收数据后如何处理，取决于上下文，以及数据业务的处理回调函数

        //1.发送数据，给用户提供的发送数据接口，把数据放到缓冲区，启动写事件监控
        void Send(const char *data, size_t len)
        {
            //外界传入的data，可能是个临时的空间，我们现在只是把发送操作压入了任务池，有可能并没有被立即执行
            //因此有可能执行的时候，data指向的空间有可能已经被释放了
            Buffer buf;
            buf.WriteAndPush(data, len);
            _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
        }

        //2.关闭连接，给用户提供的关闭连接接口，应该在实际释放连接之前，看看输入和输出缓冲区是否有数据处理
        void Shutdown()
        {
            _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
        }

        //关闭连接
        void Release()
        {
            _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
        }
        
        //3.启动非活跃连接的超时销毁功能
        void EnableInactiveRelease(int sec)
        {
            _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
        }
        
        //4.取消非活跃连接的超时销毁功能
        void CancelInactiveRelease()
        {
            _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
        }
        
        //5.协议切换，一个连接接收数据后如何处理，取决于上下文，以及数据业务的处理回调函数
        void Upgrade(const Any &context, const ConnectedCallback &conn, const MessageCallback &msg, 
                     const ClosedCallback &closed, const AnyEventCallback &event)
        {
            //防备新的事件触发后，处理的时候，切换任务还没有被执行，会导致数据使用原协议处理了
            _loop->AssertInLoop();
            _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
        }
};

//Acceptor类实现对监听套接字的管理
class Acceptor
{
    private:
        Socket _socket; //用于创建监听套接字
        EventLoop *_loop; //用于对监听套接字进行事件监控
        Channel _channel; //用于对监听套接字进行事件管理
    
        using AcceptCallback=std::function<void(int)>; //获取监听函数回调
        AcceptCallback _accept_callback; //用户设置的监听回调函数

    private:
        //监听套接字的读事件回调处理函数，获取新连接，调用_accept_callback进行新连接函数
        void HandleRead()
        {
            int newfd=_socket.Accept();
            if(newfd<0)
            {
                return ;
            }
            if(_accept_callback) _accept_callback(newfd);
        }

        //创建新连接
        int CreateServer(int port)
        {
            bool ret=_socket.CreateServer(port);
            assert(ret==true);
            return _socket.Fd();
        }

    public:
        //构造函数
        Acceptor(EventLoop *loop,int port):_socket(CreateServer(port)),_loop(loop),
                _channel(loop,_socket.Fd())
        {
            _channel.SetReadCallback(std::bind(&Acceptor::HandleRead,this));
            //_channel.EnableRead(); //启动读事件监控
        }

        //实现对回调函数的设置
        void SetAcceptCallback(const AcceptCallback &cb) 
        {
            _accept_callback = cb; 
        }
        
        //启动读事件监控
        void Listen() 
        { 
            _channel.EnableRead(); 
        }
};  

//服务器TcpServer类实现
//对所有模块进行整合，通过TcpServer模块实例化的对象，可以简单的完成一个服务器的搭建
//1.TcpServer中实例化一个Accept对象以及一个EventLoop对象
//2.将Acceptor挂到baseloop上进行事件监控
//3.一旦Acceptor对象就绪了可读事件，则执行读事件回调函数获取新连接
//4.对新连接进行管理，创建一个Connection进行管理
//5.对连接对应的Connection设置回调函数，连接完成回调，消息回调，关闭回调，任意事件回调
//6.启动Connection的非活跃连接的超时销毁规则
//7.将新连接对应的Connection挂到LoopThreadPool中的从属线程对应的Eventloop中进行事件监控
//8.一旦Connection对应的连接就绪了可读事件，这时候进行读事件回调，读取数据，读取完毕后调用TcpServer设置的消息回调
//9.业务处理中，如果长时间无通信，连接就会被销毁
class TcpServer
{
    private:
        uint64_t _next_id; //这是自动增长的连接唯一的ID
        int _port; //这是服务器要监听的端口
        int _timeout; //这是非活跃连接的统计时间，多长时间无通信就是非活跃连接
        bool _enable_inactive_release; //是否启动了非活跃连接超时销毁的判断标志
        EventLoop _baseloop; //这是主线程的EventLoop对象，负责监听事件的处理
        Acceptor _acceptor; //这是监听套接字的管理对象
        LoopThreadPool _pool; //这是从属EventLoop线程池
        std::unordered_map<uint64_t,PtrConnection> _conns; //保存管理所有连接对应的shared_ptr对象

        //这四个回调函数，是让服务器模块来设置的（其实服务器模块的处理回调也是组件使用者设置的）
        //换句话说，这几个回调都是组件使用者使用的
        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&, Buffer *)>;
        using ClosedCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        using Functor = std::function<void()>;
        ConnectedCallback _connected_callback; //用户决定的连接建立成功回调函数
        MessageCallback _message_callback; //用户决定的数据处理函数
        ClosedCallback _closed_callback; //用户决定的关闭连接回调函数
        AnyEventCallback _event_callback; //用户决定的任意事件的回调函数
    
    private:
        //添加定时任务到Loop的接口
        void RunAfterInLoop(const Functor &task,int delay)
        {
            _next_id++;
            _baseloop.TimerAdd(_next_id,delay,task);    
        }

        //为新连接构造Connection进行管理
        void NewConnection(int fd)
        {
            _next_id++;
            PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));
            conn->SetMessageCallback(_message_callback);
            conn->SetClosedCallback(_closed_callback);
            conn->SetConnectedCallback(_connected_callback);
            conn->SetAnyEventCallback(_event_callback);
            conn->SetSrvClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
            if (_enable_inactive_release) conn->EnableInactiveRelease(_timeout); //启动非活跃超时销毁
            conn->Established(); //就绪初始化
            _conns.insert(std::make_pair(_next_id, conn));
        }

        //从管理的Connection的_conns中移除信息的操作添加到Loop中
        void RemoveConnectionInLoop(const PtrConnection &conn)
        {
            int id = conn->Id();
            auto it = _conns.find(id);
            if (it != _conns.end()) 
            {
                _conns.erase(it);
            }
        }

        //从管理Connection的_conns中移除连接信息
        void RemoveConnection(const PtrConnection &conn) 
        {
            _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
        }

    public:
        //功能实现
        //设置从属线程池数量
        //启动服务器
        //设置各种回调函数，连接建立完成，消息，关闭，任意，用户设置给TcpServer，TcpServer设置给获取的新连接
        //是否启动非活跃连接超时销毁功能
        //添加定时任务功能

        //构造函数
        TcpServer(int port):
            _port(port),
            _next_id(0),
            _enable_inactive_release(false),
            _acceptor(&_baseloop,port),
            _pool(&_baseloop)
        {
            _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));
            _acceptor.Listen();//将监听套接字挂到baseloop上
        }

        //设置从属线程池数量
        void SetThreadCount(int count)
        {
            return _pool.SetThreadCount(count);
        }

        //进行回调函数的设置
        //设置各种回调函数，连接建立完成，消息，关闭，任意，用户设置给TcpServer，TcpServer设置给获取的新连接
        void SetConnectedCallback(const ConnectedCallback&cb) { _connected_callback = cb; }
        void SetMessageCallback(const MessageCallback&cb) { _message_callback = cb; }
        void SetClosedCallback(const ClosedCallback&cb) { _closed_callback = cb; }
        void SetAnyEventCallback(const AnyEventCallback&cb) { _event_callback = cb; }

        //是否启动非活跃连接超时销毁功能
        void EnableInactiveRelease(int timeout)
        {
            _timeout=timeout;
            _enable_inactive_release=true;
        }

        //添加定时任务功能
        void RunAfter(const Functor &task,int delay)
        {
            _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop,this,task,delay));
        }

        //启动服务器
        void Start()
        {
            _pool.Create();  
            _baseloop.Start();
        }
};

//移除监控
void Channel::Remove() { return _loop->RemoveEvent(this); }

//更新事件
void Channel::Update() { return _loop->UpdateEvent(this); }

//添加定时任务
void TimerWheel::TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop,this,id,delay,cb));
}

//刷新延时定时任务
void TimerWheel::TimerRefresh(uint64_t id) 
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop,this,id));
}

//取消对应id的定时任务
void TimerWheel::TimerCancel(uint64_t id) 
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop,this,id));
}

class NetWork 
{
    public:
        NetWork() 
        {
            DBG_LOG("SIGPIPE INIT");
            signal(SIGPIPE, SIG_IGN); // 忽视SIGPIPE信号(向断开的套接字中写入数据)
        }
};

static NetWork nw;

#endif